#include<iostream>
#include<WinSock2.h>
#include<thread>
#include<map>
#include<string>
#pragma warning(disable:4996)
#pragma comment (lib, "ws2_32.lib")  //加载 ws2_32.dll
using namespace std;
char szBuffer[600] = { 0 };
struct Client {
	char name[20];
	SOCKET sock;
};
map<string, SOCKET> m;
struct Msg {
	char name[20];
	char timeStamp[50];
	char msg[500];
}recvmsg;//定义数据包结构体
const int CLIENT_MAX_NUM = 5;
Client client_list[CLIENT_MAX_NUM];//最多有5个客户端
bool is_occupied[CLIENT_MAX_NUM];//记录client_list的使用情况
int CURR_OCCUPIED_NUM = 0;
void sendMsg(SOCKET sock, char str[600]) {//收到信息后转发给所有客户端
	char temp[600];
	memcpy(temp, str, 600);
	//if (!m.empty())
	//	cout << "m的大小" << m.size() << endl;
	for (auto i : m) {
		//cout << i.first << "-----" << i.second << endl;
		//if (i.second != sock) {//给自己以外的所有人发信息
		send(i.second, temp, 600 + sizeof(char), NULL);
		//}
	}
}
void c_to_s(char c[], string& s) {
	int i = 0;
	while (c[i]) {
		s[i] = c[i];
		i++;
	}
}
void s_to_c(char c[], string& s) {
	for (int i = 0; i < s.length(); i++) {
		c[i] = s[i];
	}
}
void recvMsg(SOCKET sock) {
	while (1) {
		memset(szBuffer, 0, 600);
		//接收的数据
		cout.clear();
		int ret = recv(sock, szBuffer, 600, NULL);//来自sock的信息

		char str[600] = { 0 };
		memcpy(str, szBuffer, 600);//赶紧存下来以防被覆盖

		if (ret == 0 || ret == SOCKET_ERROR) {
			if (!m.empty())
				for (map<string, SOCKET>::iterator i = m.begin(); i != m.end(); i++) {
					if (i->second == sock) {
						cout << "用户[" << i->first << "]下线了。当前在线人数为" << --CURR_OCCUPIED_NUM << endl;
						//memset(&client_list[i], 0, sizeof(struct Client));//把下线用户信息进行清除
						m.erase(i);
						break;
					}
				}

			return;
		}
		//if (szBuffer[570]) {
		char des[20];//src，私聊用户昵称
		strcpy(des, szBuffer + 570);
		if (str[20]) {
			//输出接收到的数据
			if (!str[570]) {
				int i = 20;
				while (str[i]) { cout << str[i++]; }
				cout << str;
				cout << ":";
				i = 70;
				while (str[i]) { cout << str[i++]; }
				cout << endl;
			}
			//strcpy(str+570, szBuffer + 570);
			sendMsg(sock, str);
			//cout << str[570];
		}
	}
}
int main() {
	//https://blog.csdn.net/mpp_king/article/details/80222304
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);//希望用户使用2.2版本的Socket
	//https://blog.csdn.net/m0_37624078/article/details/81217834
	SOCKET S_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	//地址类型是IPv4，服务类型是TCP所以是流式套接字，协议是TCP
	struct sockaddr_in sockAddr;//sockaddr_in用作定义，socketaddr用作函数参数
	memset(&sockAddr, 0, sizeof(sockAddr));  //将结构体清零
	sockAddr.sin_family = AF_INET;//TCP
	sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");//服务器IP
	sockAddr.sin_port = htons(1234);//端口
	//https://blog.csdn.net/will130/article/details/53326740?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-53326740-blog-97643717.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-53326740-blog-97643717.pc_relevant_aa&utm_relevant_index=1

	/*
服务端需要调用的函数有：listen、accept（慎用，运行后会阻塞）
bind、sendto、recvfrom、send、closesocket
	*/
	bind(S_socket, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
	listen(S_socket, 20);//监听服务器

	while (1) {
		SOCKADDR C_sockAddr;
		int size = sizeof(SOCKADDR);
		SOCKET C_socket = accept(S_socket, (SOCKADDR*)&C_sockAddr, &size);
		//第一个是服务器套接字，第二个是客户端SOCKADDR，第三个参数是结构体大小
		int ret = recv(C_socket, szBuffer, 600, NULL);

		if (ret <= 21) {
			string s = { 0 };
			c_to_s(szBuffer, s);
			//char des[20];
			//int i = 0;
			//while (szBuffer[i]) { des[i] = szBuffer[i]; i++; }
			m[s] = C_socket;//<str, sock>，名字作为索引
			cout << "用户[" << s << "]上线了。当前在线人数为" << ++CURR_OCCUPIED_NUM << endl;
		}
		if (C_socket != INVALID_SOCKET) {
			thread t(recvMsg, C_socket);
			t.detach();
		}
	}
	closesocket(S_socket);

	WSACleanup();
	main();
}
